﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Diagnostics;
using Bohdan.Arch.Messaging;
using System.Threading;

#pragma warning disable 0642 // Possible mistaken empty statement

namespace Bohdan.Arch.Messaging.Special
{
    public class TimeMeasurerSubscriber : GeneralThreadlessSubscriber
    {
        public readonly static Guid _Id = new Guid("{CF572D72-3A18-4bbc-BDBD-FC4364F31AC8}");
        public override Guid SubscriberId
        {
            get { return _Id; }
        }
        public override System.Threading.ThreadPriority WorkerThreadPriority
        {
            get { return System.Threading.ThreadPriority.Highest; }
        }

        protected override void ProcessMessage(GeneralMessage msg)
        {
            //Trace.TraceInformation("Message {0} queued.", msg.MeasuredMessage.ToString());
            if (msg is TimeMeasuredMessage)
            {
                TimeMeasuredMessage m = (TimeMeasuredMessage)msg;
                m.Bus.PostMessageAsync(m.MeasuredMessage);
            }
            else if (msg is TimeCheckedMessage)
            {
                TimeCheckedMessage ch = (TimeCheckedMessage)msg;
                Bus.PostMessageAsync(ch.PrimaryMessage);
                ch.StartCheckAsync(ch.Bus);
            }
            else if (msg is SequentialMessage)
            {
                SequentialMessage sm = (SequentialMessage)msg;
                foreach (GeneralMessage gm in sm.Messages)
                {
                    if (null != gm)
                    {
                        msg.Bus.PostMessageAsync(gm);
                        gm.WaitCompleted();
                    }
                }
            }
            else if (msg is ParallelMessage)
            {
                ParallelMessage pm = (ParallelMessage)msg;
                foreach (GeneralMessage gm in pm.Messages)
                    if (null != gm)
                        msg.Bus.PostMessageAsync(gm);
                foreach (GeneralMessage gm in pm.Messages)
                    if (null != gm)
                        gm.WaitCompleted();
            }
            else if (msg is WaitMessage)
            {
                Thread.Sleep(((WaitMessage)msg).Duration);
            }
            else if (msg is SmartWaitMessage)
            {
                SmartWaitMessage swm = (SmartWaitMessage)msg;

                if (swm.ActualCallback != null)
                {
                    Stopwatch sw = Stopwatch.StartNew();
                    while (sw.Elapsed < swm.Duration)
                    {
                        Thread.Sleep(swm.CheckInterval);
                        if (!swm.ActualCallback())
                            break;
                    }
                }
                else
                    Thread.Sleep(swm.Duration);
            }
            else if (msg is CancellableWaitMessage)
            {
                CancellableWaitMessage cmsg = (CancellableWaitMessage)msg;
                cmsg.DoWaitAndAction();
            }
            else if (msg is ConditionalMessage)
            {
                ConditionalMessage cmsg = (ConditionalMessage)msg;
                GeneralMessage m = cmsg.ConditionFuncWithArg(cmsg.Argument) ? cmsg.SatisfiedMsg : cmsg.UnsatisfiedMsg;
                Bus.PostMessageAsync(m);
                m.WaitCompleted();
            }
            else if (msg is SimpleActionMessage)
            {
                SimpleActionMessage smsg = (SimpleActionMessage)msg;
                if (smsg.Action != null)
                    smsg.Action();
            }
            else if (msg is WaitingMiddlemanMessage)
                ;
            else
                throw new NotImplementedException("Handling of " + msg.GetType().Name + " is not implemented.");
        }
    }
}
